// 6.5.1 特殊用途语言特性：默认实参
/**
 * 三种函数相关的语言特性，这些特性对大多数程序都有用，它们分别是：
 * 1. 默认实参
 * 2. 内联函数
 * 3. constexpr函数
 */
#include <iostream>
#include <initializer_list>
#include <iterator>
#include <vector>
using std::begin, std::end;
using std::cin, std::cout, std::endl;
using std::initializer_list;
using std::string;
using std::vector;

// 默认实参（default argument）。调用含有默认实参的函数时，可以包含该实参，也可以省略该实参。
typedef string::size_type sz;
string screen(sz ht = 24, sz wid = 80, char backgrnd = ' '); // 每个形参都提供了默认实参
// 需要注意的是，一旦某个形参被赋予了默认值，它后面的所有形参都必须有默认值。
// string screen1(sz ht = 24, sz wid, char backgrnd); // 错误

// 默认实参声明
// 对于函数的声明来说，通常的习惯是将其放在头文件中，并且一个函数只声明一次，但是多次声明同一个函数也是合法的。

// 默认实参初始化
sz wd = 80;
char def = 'C';
sz ht();
string screen1(sz = ht(),sz = wd,char=def);
void f2();

int main(int argc, char const *argv[])
{
    screen(); // 调用 screen(24,80,' ');
    screen(42);
    screen(42, 88);
    screen(42, 88, 'A');
    // screen(,,'A'); // 错误，只能省略尾部实参
    screen('?'); // 调用 screen('?',80,' ');

    f2(); //

    return 0;
}

// 对于函数定义，不能将形参默认值写进来，形参默认值应写在函数声明中
string screen(sz ht, sz wid, char backgrnd)
{
    cout << ht << " " << wid << " " << backgrnd << endl;
    return "";
}

sz ht()
{
    return 44;
}

string screen1(sz ht, sz wid, char backgrnd)
{
    cout << ht << " " << wid << " " << backgrnd << endl;
    return "";
}

void f2()
{
    def = 'D'; // 改变默认实参的值
    sz wd = 100; // 隐藏了外层定义的wd，但是没有改变默认值
    screen1(); // 调用 screen1(ht(),80,'D');
}